﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace CCL.SocketMessage
{
    /// <summary>
    /// 직렬화 가능한 Message의 Header를 제공합니다.
    /// </summary>
    public class Header : ISerializable
    {
        /// <summary>
        /// Message ID를 가져오거나 설정합니다.
        /// </summary>
        public uint MsgId { get; set; }

        /// <summary>
        /// BodyType을 가져오거나 설정합니다.
        /// </summary>
        public Constant.BodyType BodyType { get; set; }

        /// <summary>
        /// HeaderType을 가져오거나 설정합니다.
        /// </summary>
        public Constant.HeaderType HeaderType { get; set; }

        /// <summary>
        /// Body의 길이를 가져오거나 설정합니다.
        /// </summary>
        public uint BodyLength { get; set; }

        /// <summary>
        /// 해당 Message가 단편화 되었는지 가져오거나 설정합니다.
        /// </summary>
        public Constant.Fragmented Fragmented { get; set; }

        /// <summary>
        /// 마지막 Message인지 가져오거나 설정합니다.
        /// </summary>
        public Constant.LastMsg LastMsg { get; set; }
        
        /// <summary>
        /// 해당 Message의 Sequence Number를 가져오거나 설정합니다.
        /// </summary>
        public ushort SEQ { get; set; }

        /// <summary>
        /// 비어있는 Header 객체를 생성합니다.
        /// </summary>
        public Header()
        {

        }

        /// <summary>
        /// 직렬화된 byte 배열을 통해 Header 객체를 생성합니다.
        /// </summary>
        /// <param name="bytes">직렬화된 byte 배열</param>
        public Header(byte[] bytes)
        {
            MsgId = BitConverter.ToUInt32(bytes, 0);
            BodyType = (Constant.BodyType)BitConverter.ToUInt32(bytes, 4);
            HeaderType = (Constant.HeaderType)bytes[8];
            BodyLength = BitConverter.ToUInt32(bytes, 9);
            Fragmented = (Constant.Fragmented)bytes[13];
            LastMsg = (Constant.LastMsg)bytes[14];
            SEQ = BitConverter.ToUInt16(bytes, 15);
        }

        /// <summary>
        /// 바이트 배열로 직렬화 합니다.
        /// </summary>
        /// <returns>직렬화된 바이트 배열</returns>
        public byte[] GetByte()
        {
            byte[] bytes = new byte[GetSize()];

            byte[] temp = BitConverter.GetBytes(MsgId);
            Array.Copy(temp, 0, bytes, 0, temp.Length);

            temp = BitConverter.GetBytes((int)BodyType);
            Array.Copy(temp, 0, bytes, 4, temp.Length);

            bytes[8] = (byte)HeaderType;

            temp = BitConverter.GetBytes(BodyLength);
            Array.Copy(temp, 0, bytes, 9, temp.Length);

            bytes[13] = (byte)Fragmented;
            bytes[14] = (byte)LastMsg;

            temp = BitConverter.GetBytes(SEQ);
            Array.Copy(temp, 0, bytes, 15, temp.Length);

            return bytes;
        }

        /// <summary>
        /// 직렬화 가능한 객체의 바이트 사이즈를 가져옵니다.
        /// </summary>
        /// <returns>직렬화된 바이트 사이즈</returns>
        public uint GetSize()
        {
            return 17;
        }
    }
}
